import {
    WebGLRenderer,
    Scene,
    PerspectiveCamera,
    Vector3,
    MOUSE,
    Raycaster,
    Vector2,
    Camera
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TransformControls } from "three/examples/jsm/controls/TransformControls";
import { objLoader } from "./TBaseObject";
import { LightManager } from "./TLights";

export class ThreeEngine {
    dom: HTMLDivElement;
    scene: Scene;
    camera: Camera;
    renderer: WebGLRenderer;
    orbitControls: OrbitControls;
    stats: any;

    requestId: number;
    $objLoader: objLoader;
    $lightManager: LightManager;

    constructor(dom: HTMLDivElement, extData?: { stats?: any }) {
        this.dom = dom;
        this.init(extData);
    }

    init(extData?: { stats?: any }) {
        this.$objLoader = new objLoader();       //模型加载器
        this.$lightManager = new LightManager(); // 光源管理器
        this.initRenderer();
        this.initScene();
        this.initCamera();
        this.initOrbitControls();
        this.stats = extData?.stats || null;
        this.animate = this.animate.bind(this);
        this.animate();
    }

    private initRenderer() {
        this.renderer = new WebGLRenderer({
            antialias: true
        });
        this.dom.appendChild(this.renderer.domElement);
        this.renderer.setSize(this.dom.offsetWidth, this.dom.offsetHeight, true);
    }

    private initScene() {
        this.scene = new Scene();
    }

    private initCamera() {
        this.camera = new PerspectiveCamera(
            45,
            this.dom.offsetWidth / this.dom.offsetHeight,
            1,
            1000
        );
        this.camera.position.set(50, 50, 50);
        this.camera.lookAt(new Vector3(0, 0, 0));
        this.camera.up = new Vector3(0, 1, 0);
    }

    private initOrbitControls() {
        this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);
        this.orbitControls.mouseButtons = {
            LEFT: null,
            MIDDLE: MOUSE.DOLLY,
            RIGHT: MOUSE.ROTATE,
        };
    }

    private renderScene() {
        this.renderer.render(this.scene, this.camera);
    }

    animate() {
        if (this.stats !== null)
            this.stats.update();
        this.renderScene();
        this.requestId = requestAnimationFrame(this.animate);
    }

    stopAnimate() {
        cancelAnimationFrame(this.requestId);
    }

    addObject(...object: any[]) {
        object.forEach((elem) => {
            this.scene.add(elem);
        });
    }

    loadModel(url: string, type: number) {
        this.$objLoader.load(url, type, () => {
            const allBaseObject = this.$objLoader.allBaseObject;
            this.addObject(...allBaseObject);
        });
    }

    addLight() {

    }
}